| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 | 1×
1×
2×
506×
506×
506×
506×
58×
58×
40×
18×
2×
29×
2×
9×
2×
15×
68×
29×
2×
9×
2×
6×
2×
1×
176×
44×
2×
4×
2×
84×
2×
25×
2×
18×
2×
77×
2×
6×
2×
25×
97×
2×
3×
2×
9×
2×
19×
| import * as _ from 'lodash';
import { Suit, Rank, Card } from '../game.interfaces';
export function createCard(pattern: string): Card {
const CARD_PATTERN_REGEX = /([A|K|Q|J|9]|10)([♥|♦|♣|♠])/;
const result = CARD_PATTERN_REGEX.exec(pattern);
const [, rank, suit] = result;
return result && {
suit: suit as Suit,
rank: rank as Rank
};
}
export function createCards(Iinput: number|string[] = null): Card[] {
if (typeof input === 'number') {
return _.chain(createDeck())
.shuffle()
.sampleSize(input)
.value();
} else {
return _.chain(input)
.map(createCard)
.value();
}
}
export function hasKingAndQueen(cards: Card[]): boolean {
return _.some(cards, {rank: Rank.King}) && _.some(cards, {rank: Rank.Queen});
}
export function isKingOrQueen(card: Card): boolean {
return card.rank === Rank.King || card.rank === Rank.Queen;
}
export function getMarriages(cards: Card[]): Suit[] {
return _.chain(cards)
.groupBy(card => card.suit)
.reduce((marriages, suitCards, suit) => {
return hasKingAndQueen(suitCards) ? [suit, ...marriages] : marriages
}, [])
.value();
}
export function hasMarriageOfSuit(cards: Card[], suit: Suit): boolean {
return _.chain(getMarriages(cards))
.includes(suit)
.value();
}
export function hasMarriage(cards: Card[]): boolean {
return getMarriages(cards).length > 0;
}
export function createDeck(): Card[] {
function getDeckBySuit(suit: Suit): Card[] {
return [
{ rank: Rank.Ace, suit }, { rank: Rank.King, suit },
{ rank: Rank.Queen, suit }, { rank: Rank.Jack, suit },
{ rank: Rank.Ten, suit }, { rank: Rank.Nine, suit }
];
}
return [
...getDeckBySuit(Suit.Heart),
...getDeckBySuit(Suit.Diamond),
...getDeckBySuit(Suit.Club),
...getDeckBySuit(Suit.Spade)
];
}
export function createShuffledDeck(): Card[] {
return _.chain(createDeck())
.shuffle()
.value();
}
export function getCard(cards: Card[], card: Card): Card {
return _.find(cards, ({suit, rank}) => card.suit === suit && card.rank === rank);
}
export function cardExistsIn(cards: Card[], card: Card): boolean {
return !!getCard(cards, card);
}
export function hasEightCards(cards: Card[]): boolean {
return cards.length === 8;
}
export function getPointsByCard(card: Card): number {
return {
[Rank.Ace]: 11,
[Rank.King]: 4,
[Rank.Queen]: 3,
[Rank.Jack]: 2,
[Rank.Ten]: 10,
[Rank.Nine]: 0,
}[card.rank];
}
export function getTrumpPointsBySuit(suit: Suit): number {
return {
[Suit.Heart]: 100,
[Suit.Diamond]: 80,
[Suit.Club]: 60,
[Suit.Spade]: 40
}[suit];
}
export function getCardsByColor(cards: Card[], color: Suit): Card[] {
return _.chain(cards)
.filter((card: Card) => card.suit === color)
.value();
}
export function cardsWithSpecificColorExists(cards: Card[], color: Suit): boolean {
return getCardsByColor(cards, color).length > 0;
}
export function getCardWithHighestRank(cards: Card[]): Card {
return _.chain(cards)
.maxBy(getPointsByCard)
.value();
}
export function areCardsEqual(card1: Card, card2: Card): boolean {
return _.eq(card1, card2);
} |